﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/12/15 11:40:00
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;

namespace CommonLibrary
{
    /// <summary>
    /// HIOKI3153串口配置
    /// </summary>
    public class HIOKI3153ComParam : ComParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<HIOKI3153PLCEntity> PLCEntities = new List<HIOKI3153PLCEntity>();
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// HIOKI3153TCP配置
    /// </summary>
    public class HIOKI3153TcpParam : TcpParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<HIOKI3153PLCEntity> PLCEntities = new List<HIOKI3153PLCEntity>();
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 数据通知代理
    /// </summary>
    /// <param name="voltage">电压kv</param>
    /// <param name="current">电流mA</param>
    /// <param name="times">时间</param>
    /// <param name="timeType">时间类型</param>
    /// <param name="judgeResult">判定结果</param>
    /// <param name="judgeString">判定结果字符串</param>
    public delegate void NotifyHIOKI3153HelperJobDelegate(float voltage, float current, float times, int timeType, short judgeResult, string judgeString);
    /// <summary>
    /// HIOKI3153帮助类
    /// </summary>
    public class HIOKI3153Helper : BaseHelper
    {
        private object LOCK_TCP_OPT = new object();
        private object LOCK_COM_OPT = new object();
        /// <summary>
        /// TCP配置文件
        /// </summary>
        static string autoTcpHIOKI3153ConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "HIOKI3153TCPConfig.json");
        /// <summary>
        /// 串口配置文件（自动HIOKI3153）
        /// </summary>
        static string autoComHIOKI3153ConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "HIOKI3153ComConfig.json");
        #region tcp auto
        /// <summary>
        /// 获取TCPHIOKI3153配置，返回List对象
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static List<HIOKI3153TcpParam> GetAutoHIOKI3153TCPConfig()
        {
            return CommonHelper.GetJsonListFromFile<HIOKI3153TcpParam>(autoTcpHIOKI3153ConfigPath);
        }
        /// <summary>
        /// 保存TCP配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoHIOKI3153TCPConfig(List<HIOKI3153TcpParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoTcpHIOKI3153ConfigPath);
        }
        #endregion
        #region auto com
        /// <summary>
        /// 获取串口配置内容（自动HIOKI3153）
        /// </summary>
        /// <returns></returns>
        public static List<HIOKI3153ComParam> GetAutoHIOKI3153ComConfig()
        {
            return CommonHelper.GetJsonListFromFile<HIOKI3153ComParam>(autoComHIOKI3153ConfigPath);
        }
        /// <summary>
        /// 保存串口配置内容（自动HIOKI3153）
        /// </summary>
        /// <param name="list"></param>
        public static void SaveAutoHIOKI3153ComConfig(List<HIOKI3153ComParam> list)
        {
            CommonHelper.SaveToJsonFile(list, autoComHIOKI3153ConfigPath);
        }
        #endregion
        private Dictionary<string, short> mJudgeResults = new Dictionary<string, short>() {
            { "OFF",0 },//其他结果
            { "PASS",1 },//判定基准以内
            { "UFAIL",5 },//上限值<=测量值
            { "LFAIL",6 },//下限值>=测量值
            { "ULFAIL",7 },//不能判定（上限值或下限值偏离量程范围）
        };
        /// <summary>
        /// 状态检测
        /// </summary>
        private void StatusHandler(bool isOK)
        {
            var param = new HIOKIStatusExcuteEntity()
            {
                IsOK = isOK,
                StatusAddress = this.StatusAddress
            };
            #region  PLC
            PluginManager.Instance.Excute(this.Name, "HIOKI3153_STATUS_PLC", CommonHelper.GetJsonString(param, Formatting.None));
            #endregion
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public HIOKI3153Helper()
        {
            this.CustomSelfExecuteHandler = () =>
            {
                try
                {
                    if (!string.IsNullOrWhiteSpace(this.StatusAddress))
                    {
                        if (this.IsConnected)
                        {
                            var state = QueryState();
                            var isOK = state == EHIOKI3153State.WREADY ? true : false;
                            StatusHandler(isOK);
                        }
                        else
                        {
                            StatusHandler(false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            };

        }
        #region 每个Helper特定的参数
        /// <summary>
        /// 特殊延迟处理
        /// </summary>
        private static bool SPECIAL_DELAY = false;
        private static object LOCK_SPECIAL_DELAY = new object();
        /// <summary>
        /// 获取是否实行特殊延迟
        /// </summary>
        public static bool GetSpecialDelay
        {
            get
            {
                lock (LOCK_SPECIAL_DELAY)
                {
                    bool temp = SPECIAL_DELAY;
                    SPECIAL_DELAY = !SPECIAL_DELAY;
                    return temp;
                }
            }
        }
        /// <summary>
        /// 通讯超时时间，默认1000毫秒
        /// </summary>
        public override int CommunicationTimeout => BusinessConfig.Instance().H3153Timeout;
        /// <summary>
        /// 获取测量值与判定结果命令
        /// </summary>
        public const string MEASURE_STANDARD_VALUE_RESULT_COMMAND = ":MEASure:RESult:WITHstand?\r\n";
        /// <summary>
        /// 获取仪器信息
        /// </summary>
        public const string DEVICE_INFO_COMMAND = "*IDN?\r\n";
        /// <summary>
        /// 开始测试
        /// </summary>
        public const string DEVICE_START_COMMAND = ":STARt\r\n";
        /// <summary>
        /// 结束测试
        /// </summary>
        public const string DEVICE_STOP_COMMAND = ":STOP\r\n";
        /// <summary>
        /// 结束测试
        /// </summary>
        public const string DEVICE_STATE_COMMAND = ":STATe?\r\n";
        /// <summary>
        /// 设置耐压测试电压值1
        /// </summary>
        public const string WITHSTAND_VOLTAGE_COMMAND_1 = ":CONFigure:WITHstand:VOLTage 2.70\r\n";
        /// <summary>
        /// 设置耐压测试电压值2
        /// </summary>
        public const string WITHSTAND_VOLTAGE_COMMAND_2 = ":CONFigure:WITHstand:VOLTage 2.80\r\n";
        /// <summary>
        /// 数据通知处理
        /// </summary>
        public NotifyHIOKI3153HelperJobDelegate NotifyHIOKI3153HelperJob { get; set; } = null;
        #endregion
        /// <summary>
        /// PLC业务
        /// </summary>
        /// <param name="voltage">电压kv</param>
        /// <param name="current">电流mA</param>
        /// <param name="times">时间</param>
        /// <param name="timeType">时间类型</param>
        /// <param name="judgeResult">判定结果</param>
        /// <param name="judgeString">判定结果字符串</param>
        /// <param name="plcEntity">plcEntity</param>
        private void BusinessHandler(HIOKI3153PLCEntity plcEntity, float voltage, float current, float times, short timeType, short judgeResult, string judgeString)
        {
            if (plcEntity != null)
            {
                var param = new HIOKI3153ExcuteEntity()
                {
                    PlcEntity = plcEntity,
                    Voltage = voltage,
                    Current = current,
                    TimeType = timeType,
                    Times = times,
                    JudgeResult = judgeString,
                    JudgeValueResult = judgeResult
                };
                #region  PLC
                PluginManager.Instance.Excute(this.Name, "HIOKI3153_RESULT_PLC", CommonHelper.GetJsonString(param, Formatting.None));
                #endregion                
                if (this.NotifyHIOKI3153HelperJob != null)
                {
                    this.NotifyHIOKI3153HelperJob(voltage, current, times, timeType, judgeResult, judgeString);
                }
            }
        }
        /// <summary>
        /// 串口方式设置耐压测试电压值
        /// </summary>
        /// <returns></returns>
        private string DoComSetWithstandVoltage()
        {
            lock (LOCK_COM_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(WITHSTAND_VOLTAGE_COMMAND_1);
                        Thread.Sleep(BusinessConfig.Instance().H3153SetWithstandInterval);
                        this.SerialSendString(WITHSTAND_VOLTAGE_COMMAND_2);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// TCP方式设置耐压测试电压值
        /// </summary>
        /// <returns></returns>
        private string DoTcpSetWithstandVoltage()
        {
            lock (LOCK_TCP_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.TcpSend(Encoding.UTF8.GetBytes(WITHSTAND_VOLTAGE_COMMAND_1));
                        Thread.Sleep(BusinessConfig.Instance().H3153SetWithstandInterval);
                        this.TcpSend(Encoding.UTF8.GetBytes(WITHSTAND_VOLTAGE_COMMAND_2));
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// 串口方式停止测试
        /// </summary>
        /// <returns></returns>
        private string DoComStop()
        {
            lock (LOCK_COM_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(DEVICE_STOP_COMMAND);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// TCP方式停止测试
        /// </summary>
        /// <returns></returns>
        private string DoTcpStop()
        {
            lock (LOCK_TCP_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.TcpSend(Encoding.UTF8.GetBytes(DEVICE_STOP_COMMAND));
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// 串口方式启动测试
        /// </summary>
        /// <returns></returns>
        private string DoComStart()
        {
            lock (LOCK_COM_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(DEVICE_START_COMMAND);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// TCP方式启动测试
        /// </summary>
        /// <returns></returns>
        private bool DoTcpStart()
        {
            lock (LOCK_TCP_OPT)
            {
                bool success = false;
                if (this.IsConnected)
                {
                    try
                    {
                        success = this.TcpSend(Encoding.UTF8.GetBytes(DEVICE_START_COMMAND));
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return success;
            }
        }

        /// <summary>
        /// 串口方式获取状态
        /// </summary>
        /// <returns></returns>
        private EHIOKI3153State GetComState()
        {
            lock (LOCK_COM_OPT)
            {
                EHIOKI3153State result = EHIOKI3153State.NULL;
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(DEVICE_STATE_COMMAND);
                        var temp = this.GetSerialReturnUTF8String();
                        temp = string.IsNullOrWhiteSpace(temp) ? temp : CommonHelper.RemoveEnterString(temp);
                        result = CommonHelper.GetEnumByName(temp, EHIOKI3153State.NULL);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// TCP方式获取状态
        /// </summary>
        /// <returns></returns>
        private EHIOKI3153State GetTcpState()
        {
            lock (LOCK_TCP_OPT)
            {
                EHIOKI3153State result = EHIOKI3153State.NULL;
                if (this.IsConnected)
                {
                    try
                    {
                        this.TcpSend(Encoding.UTF8.GetBytes(DEVICE_STATE_COMMAND));
                        var temp = this.TcpReceiveString();
                        temp = string.IsNullOrWhiteSpace(temp) ? temp : CommonHelper.RemoveEnterString(temp);
                        result = CommonHelper.GetEnumByName(temp, EHIOKI3153State.NULL);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }

        /// <summary>
        /// 串口方式获取测量值
        /// </summary>
        /// <returns></returns>
        private string GetComMeasureValueResult()
        {
            lock (LOCK_COM_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.SerialSendString(MEASURE_STANDARD_VALUE_RESULT_COMMAND);
                        result = this.GetSerialReturnUTF8String();
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }
        /// <summary>
        /// TCP方式获取测量值
        /// </summary>
        /// <returns></returns>
        private string GetTcpMeasureValueResult()
        {
            lock (LOCK_TCP_OPT)
            {
                string result = "";
                if (this.IsConnected)
                {
                    try
                    {
                        this.TcpSend(Encoding.UTF8.GetBytes(MEASURE_STANDARD_VALUE_RESULT_COMMAND));
                        result = this.TcpReceiveString();
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }
                }
                else
                {
                    StatusHandler(false);
                }
                return result;
            }
        }

        private static char[] SPLIT_CHAR_ARRAY = new char[] { ',' };
        /// <summary>
        /// 启动测试
        /// </summary>
        /// <returns></returns>
        public void DoStart()
        {
            LogHelper.Info($"【{this.Name}】START");
            if (this.CommunicationType == ECommunicationType.SERIAL)
            {
                DoComStart();
            }
            else
            {
                DoTcpStart();
            }
        }
        /// <summary>
        /// 设置耐压测试电压值
        /// </summary>
        /// <returns></returns>
        public void DoSetWithstandVoltage()
        {
            LogHelper.Info($"【{this.Name}】SetWithstandVoltage");
            if (this.CommunicationType == ECommunicationType.SERIAL)
            {
                DoComSetWithstandVoltage();
            }
            else
            {
                DoTcpSetWithstandVoltage();
            }
        }
        /// <summary>
        /// 停止测试
        /// </summary>
        /// <returns></returns>
        public void DoStop()
        {
            LogHelper.Info($"【{this.Name}】STOP");
            if (this.CommunicationType == ECommunicationType.SERIAL)
            {
                DoComStop();
            }
            else
            {
                DoTcpStop();
            }
        }
        /// <summary>
        /// 查询状态
        /// </summary>
        /// <returns></returns>
        public EHIOKI3153State QueryState()
        {
            var result = EHIOKI3153State.NULL;
            if (this.CommunicationType == ECommunicationType.SERIAL)
            {
                result = GetComState();
            }
            else
            {
                result = GetTcpState();
            }
            return result;
        }
        /// <summary>
        /// 获取测量值，判定结果
        /// 0.00,0.0,0.0,OFF,0
        /// 电压，电流，时间，结果，时间类型
        /// </summary>
        /// <returns></returns>
        public (float voltage, float current, float testTime, short timeType, short judgeResult, string judgeString) GetMeasureValueResult()
        {
            float voltage = 0, current = 0, times = 0, floatValue = 0;
            short timeType = 0, shortValue = 0;
            short judgeResult = 0;
            string judgeString = string.Empty;
            string result = this.CommunicationType == ECommunicationType.SERIAL ? GetComMeasureValueResult() : GetTcpMeasureValueResult();
            result = CommonHelper.RemoveEnterString(result);
            if (string.IsNullOrWhiteSpace(result))
            {
                StatusHandler(false);
            }
            result = string.IsNullOrWhiteSpace(result) ? "0,0,0,OFF,0" : result;
            if (!string.IsNullOrWhiteSpace(result) && result.Contains(","))
            {

                string[] parts = result.Split(SPLIT_CHAR_ARRAY, StringSplitOptions.RemoveEmptyEntries);
                if (parts != null && parts.Length > 0)
                {
                    if (float.TryParse(parts[0], out floatValue))
                    {
                        voltage = floatValue;
                    }
                }
                if (parts != null && parts.Length > 1)
                {
                    if (float.TryParse(parts[1], out floatValue))
                    {
                        current = floatValue;
                    }
                }
                if (parts != null && parts.Length > 2)
                {
                    if (float.TryParse(parts[2], out floatValue))
                    {
                        times = floatValue;
                    }
                }

                judgeString = parts != null && parts.Length > 3 ? parts[3] : "OFF";
                if (this.mJudgeResults.ContainsKey(judgeString))
                {
                    judgeResult = this.mJudgeResults[judgeString];
                }

                if (parts != null && parts.Length > 4)
                {
                    if (short.TryParse(parts[4], out shortValue))
                    {
                        timeType = shortValue;
                    }
                }
            }
            return (voltage, current, times, timeType, judgeResult, judgeString);
        }


        /// <summary>
        /// 串口方式获取仪器信息
        /// </summary>
        /// <returns></returns>
        private string GetComDeviceInfo()
        {
            string result = "";
            if (this.IsConnected)
            {
                try
                {
                    this.SerialSendString(DEVICE_INFO_COMMAND);
                    result = this.GetSerialReturnUTF8String();
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            else
            {
                StatusHandler(false);
            }
            return result;
        }
        /// <summary>
        /// TCP方式获取仪器信息
        /// </summary>
        /// <returns></returns>
        private string GetTcpDeviceInfo()
        {
            string result = "";
            if (this.IsConnected)
            {
                try
                {
                    this.TcpSend(Encoding.UTF8.GetBytes(DEVICE_INFO_COMMAND));
                    result = this.TcpReceiveString();
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            }
            else
            {
                StatusHandler(false);
            }
            return result;
        }
        /// <summary>
        /// 获取仪器信息
        /// PC>*IDN? 
        /// 3153>HIOK,3153,0,V1.00
        /// 
        /// 制造商：HIOKI
        /// 型号：3153.
        /// 序号：0
        /// 版本：V1.00
        /// </summary>
        /// <returns></returns>
        public (string manufacturer, string model, string serialNo, string version) GetDeviceInfo()
        {
            string manufacturer = string.Empty, model = string.Empty, serialNo = string.Empty, version = string.Empty;
            string result = this.CommunicationType == ECommunicationType.SERIAL ?
                GetComDeviceInfo() : GetTcpDeviceInfo();
            result = CommonHelper.RemoveEnterString(result);
            result = string.IsNullOrWhiteSpace(result) ? string.Empty : result;
            if (!string.IsNullOrWhiteSpace(result) && result.Contains(","))
            {
                string[] parts = result.Split(SPLIT_CHAR_ARRAY, StringSplitOptions.RemoveEmptyEntries);
                if (parts != null && parts.Length > 0)
                {
                    manufacturer = parts[0];
                }
                if (parts != null && parts.Length > 1)
                {
                    model = parts[1];
                }
                if (parts != null && parts.Length > 2)
                {
                    serialNo = parts[2];
                }
                if (parts != null && parts.Length > 3)
                {
                    version = parts[3];
                }
            }
            return (manufacturer, model, serialNo, version);
        }
        /// <summary>
        /// 业务处理
        /// </summary>
        /// <param name="handlerName"></param>
        /// <param name="handlerType"></param>
        /// <param name="otherAddress"></param>
        /// <param name="otherData"></param>
        public override void RealHandler(string handlerName, EHandlerType handlerType, object otherAddress, object otherData)
        {
            this.RealShowMessage($"【{this.Name}】{handlerName}");
            float voltage = 0, current = 0, testTime = 0;
            short timeType = 0, judgeResult = 0;
            string judgeString = string.Empty;
            if (this.IsConnected)
            {
                Stopwatch stopwatch = Stopwatch.StartNew();
                try
                {
                    if (AppBasicSetting.Instance().HIOKI3153ActiveUnit.Equals(1))
                    {
                        var businessConfig = BusinessConfig.Instance();
                        #region 特殊延迟
                        if (GetSpecialDelay)
                        {
                            Thread.Sleep(businessConfig.H3153SpecialDelay);
                        }
                        #endregion

                        #region 2024-01-23 新增
                        //开始测试
                        DoStart();
                        EHIOKI3153State state = EHIOKI3153State.WTEST;

                        while (state == EHIOKI3153State.WTEST)
                        {
                            state = QueryState();
                            LogHelper.Info($"【{this.Name}】 状态：{state}");
                            Thread.Sleep(businessConfig.H3153StateInterval);
                        }
                        if (state != EHIOKI3153State.WPASS)
                        {
                            DoStop();
                            if (businessConfig.H3153NeedExtraWithstandCommand)
                            {
                                DoSetWithstandVoltage();
                            }
                        }
                        #endregion
                    }
                    var result = GetMeasureValueResult();
                    voltage = result.voltage;
                    current = result.current;
                    testTime = result.testTime;
                    timeType = result.timeType;
                    judgeResult = result.judgeResult;
                    judgeString = result.judgeString;
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
                finally
                {
                    HIOKI3153PLCEntity entity = otherAddress as HIOKI3153PLCEntity;
                    BusinessHandler(entity, voltage, current, testTime, timeType, judgeResult, judgeString);
                }
                stopwatch.Stop();
                this.RealShowMessage($"【{this.Name}】仪器测量，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，电压：{voltage.ToString("F2")} kV，" +
                    $"电流：{current.ToString("F2")} mA，{(timeType == (short)0 ? "测试时间" : (timeType == (short)1 ? "上升时间" : "下降时间"))}：{testTime.ToString("F1")} s，判定结果：{judgeString}", true);

            }
            else
            {
                StatusHandler(false);
                this.RealShowMessage($"【{this.Name}】仪器状态有问题", false);
            }
        }

    }
}
